#include "input.h"

#include "hardware/key.h"
#include "mid/input/flexible_button.h"
#include "mid/printf.h"

#include <string.h>

#define MAX_EVENT_HANDLERS 5

uint8_t CommonButtonRead(void *arg);
void CommonButtonEventCB(void *arg);

static flex_button_t gUserButtons[USER_BUTTON_MAX];
ButtonEventCallback gButtonEventHandlers[MAX_EVENT_HANDLERS];
static eButtonID gHolding = USER_BUTTON_MAX;

void InitInput()
{
	int i;
    
    memset(&gUserButtons[0], 0x0, sizeof(gUserButtons));

    for (i = 0; i < USER_BUTTON_MAX; i ++)
    {
        gUserButtons[i].id = i;
        gUserButtons[i].usr_button_read = CommonButtonRead;
        gUserButtons[i].cb = CommonButtonEventCB;
        gUserButtons[i].pressed_logic_level = 0;
        gUserButtons[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(500);
        gUserButtons[i].long_press_start_tick = FLEX_MS_TO_SCAN_CNT(1000);
        gUserButtons[i].long_hold_start_tick = FLEX_MS_TO_SCAN_CNT(1500);

        flex_button_register(&gUserButtons[i]);
    }

    memset(gButtonEventHandlers, 0, sizeof(gButtonEventHandlers));
}

void ProcessInput()
{
    flex_button_scan();
    if (gHolding != USER_BUTTON_MAX)
    {
        for (int i = 0; i < MAX_EVENT_HANDLERS; i++)
        {
            if (gButtonEventHandlers[i] != NULL)
            {
                int intercepted = gButtonEventHandlers[i](gHolding, FLEX_BTN_PRESS_LONG_HOLD);
                if (intercepted)
                    break;
            }
        }
    }
}

int RegisterButtonEventHandler(ButtonEventCallback handler)
{
    if (handler == NULL)
        return 0;

    for (int i = 0; i < MAX_EVENT_HANDLERS; i++)
    {
        if (gButtonEventHandlers[i] == NULL)
        {
            gButtonEventHandlers[i] = handler;
            return 1;
        }
    }

    return 0;
}

void UnRegisterButtonEventHandler(ButtonEventCallback handler)
{
    if (handler == NULL)
        return;

    for (int i = 0; i < MAX_EVENT_HANDLERS; i++)
    {
        if (gButtonEventHandlers[i] == handler)
        {
            i++;
            while (i < MAX_EVENT_HANDLERS && gButtonEventHandlers[i] != NULL)
            {
                gButtonEventHandlers[i-1] = gButtonEventHandlers[i];
                i++;
            }
            gButtonEventHandlers[i-1] = NULL;
            break;
        }
    }
}

uint8_t CommonButtonRead(void *arg)
{
    uint8_t value = 0;

    flex_button_t *btn = (flex_button_t *)arg;
	KeyValues keys = ScanKeys();

    switch (btn->id)
    {
    case USER_BUTTON_UP:
        value = keys.up;
        break;
    case USER_BUTTON_DOWN:
        value = keys.down;
        break;
    case USER_BUTTON_LEFT:
        value = keys.left;
        break;
    case USER_BUTTON_RIGHT:
        value = keys.right;
        break;
	case USER_BUTTON_MID:
        value = keys.mid;
        break;
    // default:
    //     RT_ASSERT(0);
    }

    return value;
}

void CommonButtonEventCB(void *arg)
{
    flex_button_t *btn = (flex_button_t *)arg;

    if (btn->event == FLEX_BTN_PRESS_LONG_HOLD)
        gHolding = btn->id;
    else if (btn->event == FLEX_BTN_PRESS_LONG_HOLD_UP)
        gHolding = USER_BUTTON_MAX;

    for (int i = 0; i < MAX_EVENT_HANDLERS; i++)
    {
        if (gButtonEventHandlers[i] != NULL)
        {
            int intercepted = gButtonEventHandlers[i](btn->id, btn->event);
            if (intercepted)
                break;
        }
    }
}

